import {defineStore} from "pinia";
import {reqImServiceInfo, reqOfflineMessageList, reqFriendList} from "@/api/index.js";
import {getToken, getUserId} from "@/util/LocalUtils.js";
import {formatDateAndTime, formatHourAndMinute, formatMonthAndDay, formatYear} from "@/util/DateUtils.js";
import LinkedList from "@/list/LinkedList.js";
import {ref} from "vue";

const useSessionStore = defineStore('session', () => {
    let webSocket = null;
    let loading = false

    const sessionList = ref([])
    const sessionIndex = ref(-1)
    function getSession() {
        if (sessionIndex.value < 0) {
            return null
        }
        return sessionList.value[sessionIndex.value]
    }
    async function init() {
        if (webSocket != null) {
            return
        }
        const [friendList, serviceInfo] = await Promise.all([
            reqFriendList(), reqImServiceInfo()])
        webSocket = initWebSocket(serviceInfo.data)
        sessionList.value = initSessionList(friendList.data)

        function initWebSocket(serviceInfo) {
            const {host, port} = serviceInfo
            const socket = new WebSocket("ws://" + host + ":" + port + "/ws");
            socket.onopen = () => {
                socket.send('{"header":{"command":1000},"content":{"token":"' + getToken() + '"}}')
            }
            socket.onmessage = (event) => {
                const data = JSON.parse(event.data)
                if (data.header.command === 2000) {
                    const message = data.content
                    const date = new Date()
                    const timestamp = date.getTime()
                    const currDay = date.setHours(0, 0, 0, 0)
                    const currYear = date.setMonth(0, 1)
                    message['time'] = formatDateAndTime(timestamp)

                    let index = -1
                    for (let i = 0; i < sessionList.value.length; i++) {
                        if (sessionList.value[i].userId === message.sourceId) {
                            index = i
                            break;
                        }
                    }
                    if (index === -1) {
                        return
                    }

                    sessionList.value[index]['message'] = message.message
                    sessionList.value[index]['time'] = getSessionTime(currYear, currDay, timestamp)
                    sessionList.value[index].messageList.addLast(message)
                    let tempUser = sessionList.value[0]
                    sessionList.value[0] = sessionList.value[index]
                    for (let i = 1; i <= index; i++) {
                        let temp = sessionList.value[i]
                        sessionList.value[i] = tempUser
                        tempUser = temp
                    }

                    if (sessionIndex.value !== -1) {
                        const sessionUser = sessionList.value[sessionIndex.value]
                        index = Math.min(sessionIndex.value + 1, sessionList.value.length - 1)
                        for (let i = index; i >= 0; i--) {
                            if (sessionList.value[i].userId === sessionUser.userId) {
                                sessionIndex.value = i
                                break;
                            }
                        }
                    }

                    sessionList.value[0]['messageCount'] = (sessionList.value[0]['messageCount'] || 0) + 1
                    socket.send('{"header":{"command":2002},"content":{"messageId":' + message.messageId + ',"clientId":"' + message.clientId + '"}}')
                } else if (data.header.command === 2001) {
                    let messageList = null
                    for (let i = 0; i < sessionList.value.length; i++) {
                        if (sessionList.value[i].userId === data.content.targetId) {
                            messageList = sessionList.value[i]['messageList']
                            break
                        }
                    }
                    if (messageList === null) {
                        return;
                    }
                    for (let message of messageList.reverseIterator()) {
                        if (data.content.clientId === message.clientId) {
                            message.sending = false;
                            message.messageId = data.content.messageId
                            message.messageStatus = 3
                            break;
                        }
                    }
                }
            }
            socket.onerror = () => {
                console.log("error")
                socket.close()
            }
            socket.onclose = async () => {
                console.log("close")
                const resp = await reqImServiceInfo()
                initWebSocket(resp.data)
            }
            return socket
        }

        function initSessionList(userList) {
            const date = new Date()
            const currDay = date.setHours(0, 0, 0, 0)
            const currYear = date.setMonth(0, 1)
            userList.forEach(item => {
                let messageList = item.messageList
                item.messageList = new LinkedList()
                let count = 0;
                if (messageList !== undefined) {
                    for (let message of messageList) {
                        if (message.messageStatus === 3) {
                            break
                        }
                        count++;
                    }
                    const last = messageList[0]
                    item['message'] = last.message
                    item['createdOn'] = last.createdOn
                    item['time'] = getSessionTime(currYear, currDay, last.createdOn)
                } else {
                    item['message'] = ''
                    item['createdOn'] = -1
                    item['time'] = ''
                }
                item['messageCount'] = count;
                setMessageList(item, messageList)
            })
            userList.sort((v1, v2) => v2.createdOn - v1.createdOn)
            return userList
        }
    }

    async function changeSession(param) {
        loading = true
        const {index, session} = param
        if (session.messageCount > 0) {
            session.messageCount = 0
            if (session.messageList.isNotEmpty()) {
                const message = session.messageList.getLast()
                webSocket.send('{"header":{"command":2003},"content":{"messageId":' + message.messageId + ',"clientId":"' + message.clientId + '"}}')
            }
        }
        if (session.messageList.isEmpty() || session.messageList.length() < 20) {
            const params = {userId: getUserId(), sessionUserId: session.userId};
            if (session.messageList.isNotEmpty()) {
                params['maxMsgId'] = session.messageList.getFirst().messageId
            }
            const resp = await reqOfflineMessageList(params)
            const messageList = resp.data
            setMessageList(session, messageList)
        }
        sessionIndex.value = index
        loading = false
    }

    async function getMessageList() {
        if (loading) {
            return
        }
        loading = true
        const sessionUser = sessionList.value[sessionIndex.value]
        let resp
        if (sessionUser.messageList.isNotEmpty()) {
            resp = await reqOfflineMessageList({sessionUserId: sessionUser.userId,
                maxMsgId: sessionUser.messageList.getFirst().messageId})
        } else {
            resp = await reqOfflineMessageList({sessionUserId: sessionUser.userId})
        }
        setMessageList(sessionUser, resp.data)
        loading = false
    }

    function scrollMessage() {
        const session = getSession()
        if (session.messageCount === 0) {
            return;
        }
        const message = session.messageList.getLast()
        webSocket.send('{"header":{"command":2003},"content":{"messageId":' + message.messageId + ',"clientId":"' + message.clientId + '"}}')
        session.messageCount = 0
        message.messageStatus = 3
    }

    function sendMessage(message) {
        const date = new Date()
        const timestamp = date.getTime()
        message['clientId'] = timestamp + ''
        webSocket.send('{"header":{"command":2000},"content":' + JSON.stringify(message) + '}')
        const currDay = date.setHours(0, 0, 0, 0)
        const currYear = date.setMonth(0, 1)
        message['time'] = formatDateAndTime(timestamp)
        message['sourceType'] = 0

        sessionList.value[sessionIndex.value]['message'] = message.message
        sessionList.value[sessionIndex.value]['time'] = getSessionTime(currYear, currDay, timestamp)
        sessionList.value[sessionIndex.value].messageList.addLast(message)
        let tempUser = sessionList.value[0]
        sessionList.value[0] = sessionList.value[sessionIndex.value]
        for (let i = 1; i <= sessionIndex.value; i++) {
            let temp = sessionList.value[i]
            sessionList.value[i] = tempUser
            tempUser = temp
        }
        sessionIndex.value = 0
    }

    function getSessionTime(currYear, currDay, timestamp) {
        if (timestamp < currYear) {
            return formatYear(timestamp)
        } else if (timestamp < currDay) {
            return formatMonthAndDay(timestamp)
        } else {
            return formatHourAndMinute(timestamp)
        }
    }

    function setMessageList(user, messageList) {
        if (messageList === undefined || messageList === null || messageList.length === 0) {
            return;
        }
        for (let i = 0; i < messageList.length; i++) {
            const message = messageList[i]
            if (message.messageType === 2) {
                message.message = JSON.parse(message.message)
            }
            message['time'] = formatDateAndTime(message.createdOn)
            user.messageList.addFirst(message)
        }
    }

    return {
        sessionList, sessionIndex, init, changeSession, getSession, getMessageList, scrollMessage, sendMessage
    }
})

export default useSessionStore